package reflection;

import org.junit.jupiter.api.Test;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author DCSGO
 * @version 1.0
 * 通过反射获取类的结构信息
 */
public class ReflectionUtils {
    //第四组API 获得构造器的详细信息
    @Test
    void T4() throws ClassNotFoundException {
        Class<?> personCls = Class.forName("reflection.Person");
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.print(personCls.getSimpleName() +
                    "的构造器：" + declaredConstructor.getName() +
                    "\t访问权限修饰符的值 = " + declaredConstructor.getModifiers() +
                    "\t参数列表：");
            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.print(parameterType.getSimpleName() + ", ");
            }
            System.out.println();
        }
        /*
         * Person的构造器：reflection.Person	访问权限修饰符的值 = 4	参数列表：double,
         * Person的构造器：reflection.Person	访问权限修饰符的值 = 2	参数列表：float,
         * Person的构造器：reflection.Person	访问权限修饰符的值 = 0	参数列表：int,
         * Person的构造器：reflection.Person	访问权限修饰符的值 = 1	参数列表：String,
         * Person的构造器：reflection.Person	访问权限修饰符的值 = 1	参数列表：
         */
    }

    //第三组API 获得方法的详细信息
    @Test
    void T3() throws ClassNotFoundException {
        //getReturnTyp 以 Class 形式返回方法的返回值类型
        //getParameterTypes 以 Class[] 返回参数类型数组
        Class<?> personCls = Class.forName("reflection.Person");
        Method[] methods = personCls.getDeclaredMethods();
        for (Method method : methods) {
            System.out.print(personCls.getSimpleName() +
                    "的方法：" + method.getName() +
                    "\t访问权限修饰符的值 = " + method.getModifiers() +
                    "\t返回类型是：" + method.getReturnType() +
                    "\t参数列表："
            );
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.print(parameterType.getSimpleName() + ", ");
            }
            System.out.println();
        }
        /*
         * Person的方法：m1	访问权限修饰符的值 = 1	返回类型是：int	参数列表：String, double,
         * Person的方法：m2	访问权限修饰符的值 = 0	返回类型是：void	参数列表：
         * Person的方法：m4	访问权限修饰符的值 = 2	返回类型是：void	参数列表：
         * Person的方法：m3	访问权限修饰符的值 = 4	返回类型是：void	参数列表：
         */
    }


    //第二组API 获得字段的详细信息
    @Test
    void T2() throws ClassNotFoundException {
        //1.getModifiers: 以int形式返回修饰符
        //[说明:默认修饰符是0 public是1 private是2 protected是4 static是8 final是16
        // 有多个修饰符返回的就是他们的和]
        //2.getType:以Class形式返回类型
        //3.getName:返回属性名

        Class<?> personCls = Class.forName("reflection.Person");
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(personCls.getSimpleName() + "的字段：" +
                    declaredField.getName() + "\t的修饰符值 = " +
                    declaredField.getModifiers() + "\t类型是：" +
                    declaredField.getType().getName());
        }
        /* 12=4+8 protected static
         * Person的字段：name	的修饰符值 = 1	类型是：java.lang.String
         * Person的字段：age	    的修饰符值 = 0	类型是：int
         * Person的字段：weight	的修饰符值 = 12	类型是：double
         * Person的字段：sal	    的修饰符值 = 2	类型是：float
         */
    }

    //第一组API 获得字段、方法、构造器对应的 Class 对象
    @Test
    void T1() throws ClassNotFoundException {
        Class<?> personCls = Class.forName("reflection.Person");
        //获取全类名
        System.out.println(personCls.getName());//reflection.Person
        //获取简单类名
        System.out.println(personCls.getSimpleName());//Person
        //以Package形式返回包信息
        System.out.println(personCls.getPackage());//package reflection
        //获取所有 public 修饰的属性包括本类以及父类的
        Field[] fields = personCls.getFields();
        for (Field field : fields) {
            System.out.print(field.getName() + " ");
        }//name f1

        System.out.println();
        //获取本类中的所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.print(declaredField.getName() + " ");
        }//name age weight sal

        System.out.println();
        //获取所有 public 方法包括本类的和父类的
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.print(method.getName() + " ");
        }//m1 Am1 wait wait wait equals toString hashCode getClass notify notifyAll

        System.out.println();
        //获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.print(declaredMethod.getName() + " ");
        }//m3 m2 m1 m4

        System.out.println();
        //获取所有 public 修饰的构造器
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(personCls.getSimpleName() + "的public构造器：" + constructor);
        }
        //Person的public构造器：public reflection.Person(java.lang.String)
        //Person的public构造器：public reflection.Person()

        System.out.println();
        //获取本类所有构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(personCls.getSimpleName() + "的所有构造器：" + declaredConstructor);
        }
        /*
         * Person的所有构造器：protected reflection.Person(double)
         * Person的所有构造器：private reflection.Person(float)
         * Person的所有构造器：reflection.Person(int)
         * Person的所有构造器：public reflection.Person(java.lang.String)
         * Person的所有构造器：public reflection.Person()
         *
         */

        //以Class形式返回父类信息
        System.out.println(personCls.getSuperclass());//class reflection.A

        //以Class[]形式返回接口信息
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface);
        }//interface java.io.Serializable

        //以Annotation[]形式返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }//@java.lang.Deprecated()
    }
}

class A {
    public int f1;
    boolean f2;
    protected float f3;
    private double f4;

    public void Am1() {
    }

    void Am2() {
    }

    protected void Am3() {
    }

    private void Am4() {
    }

    public A() {
    }

    public A(int f1) {
        this.f1 = f1;
    }

    A(boolean f2) {
        this.f2 = f2;
    }

    protected A(float f3) {
        this.f3 = f3;
    }

    private A(double f4) {
        this.f4 = f4;
    }
}

@Deprecated
class Person extends A implements Serializable {
    public String name;
    int age;
    protected static double weight;
    private float sal;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    Person(int age) {
        this.age = age;
    }

    private Person(float sal) {
        this.sal = sal;
    }

    protected Person(double weight) {
        this.weight = weight;
    }

    public int m1(String name, double height) {
        return 10;
    }

    void m2() {
    }

    protected void m3() {
    }

    private void m4() {
    }

}